package mongodb

import (
	"GoServer/utils/debug"
	"context"
	"errors"
	"fmt"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	"time"
)

//	err = ExecuteWithTransaction(client, func(sc mongo.SessionContext) error {
//		// 执行插入、更新或删除操作
//		// ...
//		return nil // 表示成功
//	})
//
// 通用事务处理函数，接收自定义的事务操作函数，并在失败时重试
func ExecuteWithTransactionAndRetry(client *mongo.Client, operation func(sc mongo.SessionContext) error, maxRetries int) error {
	for attempt := 1; attempt <= maxRetries; attempt++ {
		debug.Logf(debug.Debug, fmt.Sprintf("事物尝试 %d", attempt))

		// 创建会话
		session, err := client.StartSession()
		if err != nil {
			return fmt.Errorf("failed to start session: %v", err)
		}
		defer session.EndSession(context.TODO())

		// 执行事务操作
		err = mongo.WithSession(context.TODO(), session, func(sc mongo.SessionContext) error {
			// 启动事务
			if err := session.StartTransaction(); err != nil {
				return fmt.Errorf("failed to start transaction: %v", err)
			}

			// 执行用户定义的操作
			if err := operation(sc); err != nil {
				// 操作失败，回滚事务
				err := session.AbortTransaction(sc)
				if err != nil {
					return err
				}
				return fmt.Errorf("transaction aborted due to error: %v", err)
			}

			// 提交事务
			if err := session.CommitTransaction(sc); err != nil {
				return fmt.Errorf("failed to commit transaction: %v", err)
			}

			return nil
		})

		if err == nil {
			// 如果没有错误，退出循环
			return nil
		}

		// 如果事务失败，且仍在最大重试次数内，打印错误信息并重试
		fmt.Printf("Transaction failed: %v", err)
		if attempt == maxRetries {
			return fmt.Errorf("transaction failed after %d attempts: %v", maxRetries, err)
		}

		// 延迟一段时间后重试（可选，根据需求调整）
		time.Sleep(1 * time.Second)
	}

	return nil
}

// / 插入数据
func InsertCollection(collection *mongo.Collection, data interface{}) error {
	debug.Logf(debug.Debug, fmt.Sprintf("Insert Collection: %s, Filter: %+v", collection.Name(), data))
	start := time.Now()

	_, err := collection.InsertOne(context.TODO(), data)
	if err != nil {
		return err
	}

	debug.Logf(debug.Debug, fmt.Sprintf("Insert operation took: %v", time.Since(start)))
	return nil
}

// InsertOrUpdateCollection 插入或更新集合中的文档（按指定 filter 匹配）
// 如果文档存在则更新，不存在则插入
func InsertOrUpdateCollection(collection *mongo.Collection, filter interface{}, data interface{}) error {
	debug.Logf(debug.Debug, fmt.Sprintf("InsertOrUpdate Collection: %s, Filter: %+v", collection.Name(), filter))
	start := time.Now()

	update := bson.M{"$set": data}
	opts := options.Update().SetUpsert(true)

	_, err := collection.UpdateOne(context.TODO(), filter, update, opts)
	if err != nil {
		return err
	}

	debug.Logf(debug.Debug, fmt.Sprintf("InsertOrUpdate operation took: %v", time.Since(start)))
	return nil
}

// / 更新数据
// Update operation
func UpdateCollection(collection *mongo.Collection, filter bson.M, update bson.M) error {
	debug.Logf(debug.Debug, fmt.Sprintf("Update Collection: %s, Filter: %+v", collection.Name(), filter))
	start := time.Now()

	// 执行更新操作
	result, err := collection.UpdateOne(context.TODO(), filter, update)
	if err != nil {
		debug.Logf(debug.Info, fmt.Sprintf("Update operation failed: %v", err))
		return err
	}

	// 打印匹配和修改的文档数
	debug.Logf(debug.Info, fmt.Sprintf("Matched %d document(s) and modified %d document(s).", result.MatchedCount, result.ModifiedCount))
	debug.Logf(debug.Info, fmt.Sprintf("Update operation took: %v", time.Since(start)))
	return nil
}

// / 删除数据
func DeleteCollection(collection *mongo.Collection, filter bson.M) error {
	debug.Logf(debug.Debug, fmt.Sprintf("Delete Collection: %s, Filter: %+v", collection.Name(), filter))
	start := time.Now()

	// 执行删除操作
	result, err := collection.DeleteOne(context.TODO(), filter)
	if err != nil {
		debug.Logf(debug.Info, fmt.Sprintf("Delete operation failed: %v", err))
		return err
	}

	// 打印删除的文档数
	debug.Logf(debug.Info, fmt.Sprintf("Deleted %d document(s).", result.DeletedCount))
	debug.Logf(debug.Info, fmt.Sprintf("Delete operation took: %v", time.Since(start)))
	return nil
}

func CheckCollectionExists(collection *mongo.Collection, filter bson.M) (bool, error) {
	start := time.Now()
	// 执行查询
	count, err := collection.CountDocuments(context.TODO(), filter)
	if err != nil {
		return false, fmt.Errorf("failed to check order existence: %v", err)
	}

	exists := count > 0
	debug.Logf(debug.Info, fmt.Sprintf("Check Collection Exists took: %v", time.Since(start)))
	return exists, nil
}

// / 条件查找
func QueryByCollectionAndFilter(collection *mongo.Collection, filter bson.M) (interface{}, error) {
	debug.Logf(debug.Debug, fmt.Sprintf("Query Collection: %s, Filter: %+v", collection.Name(), filter))

	start := time.Now()

	var result interface{}
	err := collection.FindOne(context.Background(), filter).Decode(&result)
	if err != nil {
		if errors.Is(err, mongo.ErrNoDocuments) {
			debug.Logf(debug.Debug, fmt.Sprintf("No documents found, Time taken: %v", time.Since(start)))
			return nil, nil // 返回nil表示未找到
		}
		debug.Logf(debug.Debug, fmt.Sprintf("Error querying collection: %v, Time taken: %v", err, time.Since(start)))
		return nil, err
	}

	debug.Logf(debug.Debug, fmt.Sprintf("Found document: %+v, Time taken: %v", result, time.Since(start)))
	return result, nil
}

// DocumentExists 判断某个集合中是否存在满足条件的文档
func DocumentExists(collection *mongo.Collection, filter interface{}) (bool, error) {
	count, err := collection.CountDocuments(context.TODO(), filter)
	if err != nil {
		return false, err
	}
	return count > 0, nil
}
